iT邦幫忙

2023 iThome 鐵人賽

DAY 3
0
Modern Web

Phoenix 1.7 完全教學系列 第 3 篇

3 快速上手夠用的 Elixir (模組, 函式)

  • 分享至 

  • xImage
  •  

之所以說 Elixir 簡單,是因為比起物件導向,Elixir 只有 Function(函式) 沒有其他太抽象的隱藏概念,所有的組成都非常直覺。

定義 Module

定義 Module 使用 defmodule 關鍵字,並用 do 與 end 來將內容包起來。 Module 名稱使用 camel case.

defmodule MyModule do
end

定義 Function

所有的 function 都必須要在模組底下定義

defmodule MyModule do
  def my_function do
    "Hello World"
  end
end

我們可以這樣呼叫

MyModule.my_function #=> "Hello World"

定義帶有參數的 Function

使用() 設定參數,並用 , 分隔

def add_them(first, second) do
  first + second
end

def add_them(first, second, third) do
  first + second + third
end

在 Elixir 裡面同一個模組可以有相同名字的函式,在稱呼這個函式的時候我們會一起寫上他的變數數量(arity),上面兩個函式分別是 add_them/2 與 add_them/3,另外相同名字與相同 arity 的函式也是允許的,執行順序由上至下,這個在下個章節會說明。

執行 .ex 檔案

在上一篇我們都是使用 iex 來執行 Elixir 程式碼,但是在這邊要編輯並執行長一點的程式碼段落會很不方便,
我們可以使用編輯器並存成 .ex 檔案,通常會依照模組的名稱命名,如剛剛的範例可以叫:my_module.ex
接著可以在終端機執行 elixir my_module.ex 來執行它,

另外,在目前的章節,使用 iex 讀入該 module,再來執行會比較方便,
可以使用 iex my_module.ex 來開啟 iex 並執行該檔案內的程式碼
或是進入 iex 之後 使用 c("my_module.ex") 來讀取並執行

小測驗

寫一個匯率轉換小程式,他的執行結果如下
(這邊先不用考慮精準度與匯率,先寫個極簡單版本熟悉 Module 與 function 即可)

iex "ex_currency.ex"
ExCurrency.to_usd(300)
#=> 30
ExCurrency.to_jpy(300)
#=> 1200

參考解答

# ex_currency.ex
defmodule ExCurrency do
  def to_usd(twd) do
    div(twd, 30)
  end
  
  def to_jpy(twd) do
    twd * 4
  end
end

省略 Module

有幾個情況可以省略 module

  1. 呼叫同一個 Module 底下的另一個 function
defmodule ExCurrency do
  def to_jpy(twd) do
    twd * 4
  end
  
  def twd_2000_to_jpy() do
    to_jpy(2000) #=> 這邊前面可以省略 ExCurrency
  end
end
  1. 屬於 Kernel module 的 function 可以直接呼叫
is_atom(:hi) #=> true

Kernel 文件可以看所有的 Kernel 函式

  1. 有 import 該 module

拿剛剛的小測驗為例
使用 iex ex_currency.ex 進入 iex 後
再執行 import ExCurrency

我們就可以直接呼叫 to_jpy/1 function

匿名函式

使用 fn, -> 與 end 定義匿名函式

to_jpy = fn twd -> twd * 4 end

多行的情況

to_jpy = fn twd ->
  # 很多行的複雜運算
  twd * 4
end

簡寫,省去變數名稱,在 &() 內由 &1 代表第一個變數,依此類推

to_jpy = &(&1 * 4)

直接執行匿名函式需要加一個 .
不過實際上比較少這樣執行

to_jpy.(300)
#=> 1200

通常會在 Enum.map/2 或 Enum.reduce/3 等高階函式使用
(高階函式:使用一個或多個函式當作變數的函式)

將函式當作變數

在 Functional programming 中,function 可以被當作變數傳遞,

常見的情形如 Enum.map/2

匿名函式的情況

Enum.map([1, 2, 3], fn x -> x + 1 end)

普通函式,則是加上 & 並使用 / 標記上 arity

Enum.map(["one", "two", "three"], &String.upcase/1)
#=> ["ONE", "TWO", "THREE"]

常用的內建模組

除了可以省略模組的 Kernel 外 (其實 +, - 也是 Kernel 的函式)

我們寫應用的時候最常使用到的有下面幾個

List.first([1, 2, 3])
#=> 1
List.delete([:a, :b, :c], :d)
#=> [:a, :b, :c]

要注意的是,list 這個型別有 Enumerable protocol 所以可以使用 Enum 模組的函式
其實平常使用在 list 上的函式屬於 Enum 模組的情況還比較常見

Enum.count([1, 2, 3])
#=> 3
Enum.map([1, 2, 3], fn x -> x * 2 end)
#=> [2, 4, 6]
Enum.sort([3, 2, 1])
#=> [1, 2, 3]

在寫 Phoenix 應用的時候常常要處理 Map 與 Struct(之後介紹)

Map.get(%{name: "Jack", age: 3}, :name)
#=> "Jack"

Map.merge(%{a: 1, b: 2}, %{a: 3, d: 4})
#=> %{a: 3, b: 2, d: 4}

Map.keys(%{a: 1, b: 2})
[:a, :b]

收集了字串相關的方法,如

String.downcase("ABCD")
#=> "abcd"
String.replace("a,b,c", ",", "-")
#=> "a-b-c"

上一篇
2 快速上手夠用的 Elixir (IEX, 型別)
下一篇
4 快速上手夠用的 Elixir (Pattern matching)
系列文
Phoenix 1.7 完全教學 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言